#pragma once
#define int8_t	sint8_t
#include <stdint.h>
#undef	int8_t

#define int8_t char

#define SM4_BLOCK_SIZE       (16)

typedef struct
{
	/*!<  SM4 subkeys       */
    uint32_t sk[32];

	/*initial vector */
	uint8_t iv[SM4_BLOCK_SIZE];
}sm4_ctx_t;

typedef struct
{
	void (*enckey)(sm4_ctx_t *ctx, uint8_t* key);
	void (*deckey)(sm4_ctx_t *ctx, uint8_t* key);
	int32_t (*encdata)(sm4_ctx_t *ctx, int32_t len, uint8_t *input, uint8_t *output);
	int32_t (*decdata)(sm4_ctx_t *ctx, int32_t len, uint8_t *input, uint8_t *output);
}sm4_func_t;

enum
{
	SM4_MODE_ECB,
	SM4_MODE_CBC,
	SM4_MODE_CFB,
	SM4_MODE_OFB,
	SM4_MODE_CTR,
	SM4_MODE_MAX,
};

void gm_sm4_register(sm4_func_t *op);
void gm_sm4_unregister(void);

/**
 * desc		SM4 mode block encryption/decryption create
 * type		SM4 mode
 */
int32_t gm_sm4_create(uint32_t type);
int32_t gm_sm4_destroy(void);

/**
 * desc          SM4 key schedule (128-bit, encryption)
 *
 * param ctx      SM4 context to be initialized
 * param key      16-byte secret key
 */
int32_t gm_sm4_enckey(sm4_ctx_t *ctx, uint8_t* key);

/**
 * desc          SM4 key schedule (128-bit, decryption)
 *
 * param ctx      SM4 context to be initialized
 * param key      16-byte secret key
 */
int32_t gm_sm4_deckey(sm4_ctx_t *ctx, uint8_t* key);

/**
 * desc			SM4 block encryption/decryption
 * param ctx	SM4 context
 * param len	length of the input data
 * param input	input block
 * param output	output block
 */
int32_t gm_sm4_encrypt(sm4_ctx_t *ctx, uint32_t len, uint8_t *input, uint8_t *output);
int32_t gm_sm4_decrypt(sm4_ctx_t *ctx, uint32_t len, uint8_t *input, uint8_t *output);
